﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Irony.Parsing;
using NMF.Transformations;
using NMF.Utilities;
using NMF.Languages.AnyText.ClassConstruction;
using NMF.Transformations.Simples;

namespace NMF.Languages.AnyText.Transformations
{
    public class AnyTextTransformation : Transformation
    {
        protected override IEnumerable<GeneralTransformationRule> CreateAllTransformationRules()
        {
            yield return new AnyTextGrammarTransformationRule();
            yield return new LanguageTransformationRule();
            yield return new LanguageMemberTransformationRule();
            yield return new RuleTransformationRule();
            yield return new RuleNameReferenceTransformationRule();
            yield return new RuleImplementationTransformationRule();
            yield return new RulePartTransformationRule();
            yield return new LiteralTransformationRule();
            yield return new KeywordTransformationRule();
            yield return new IdentifierTransformationRule();
            yield return new IdentifierReferenceTransformationRule();
            yield return new QuestionMarkTransformationRule();
            yield return new PlusTransformationRule();
            yield return new StarTransformationRule();
            yield return new ParanthesisRule();
            yield return new PropertyTransformationRule();
            yield return new InheritanceTransformationRule();
            yield return new TypeExpressionRule();
            yield return new TypeTransformationRule();
            yield return new TypeReferenceTransformationRule();
            yield return new TypeExpressionTransformationRule();
            yield return new RuleReferenceTransformationRule();
            yield return new BaseOptionTransformationRule();
            yield return new StringTransformationRule();
            yield return new StringLengthTransformationRule();
            yield return new IntegerTransformationRule();
            yield return new IntegerMaximumRule();
            yield return new IntegerMinimumRule();
            yield return new FloatTransformationRule();
            yield return new FloatMaximumRule();
            yield return new FloatMinimumRule();
            yield return new BooleanTransformationRule();
            yield return new BooleanFalseStringRule();
            yield return new BooleanTrueStringRule();
            yield return new RegexTransformationRule();
            yield return new RegexPatternRule();
            yield return new RegexMultilineRule();
            yield return new EnumTransformationRule();
            yield return new EnumIgnoreCaseRule();
            yield return new EnumLiteral();
            yield return new IdentifierDefaultsSectionTransformationRule();
            yield return new IdentifierDefaultsTransformationRule();
            yield return new CommentsTransformationRule();
        }

        private static AnyTextInternalGrammar AnyText
        {
            get
            {
                return AnyTextInternalGrammar.Instance;
            }
        }

        protected virtual AnyTextGrammar CreateGrammar()
        {
            return new AnyTextGrammar();
        }

        public virtual AnyTextGrammar CreateGrammar(ParseTree parseTree)
        {
            return TransformationEngine.Transform<ParseTree, AnyTextGrammar>(parseTree, this);
        }

        class AnyTextGrammarTransformationRule : SimpleTransformationRule<ParseTree, AnyTextGrammar>
        {
            public override void Transform(ParseTree input, AnyTextGrammar output, ITransformationContext context)
            {
                output.Root = context.Trace.FindAllIn(Rule<RuleTransformationRule>()).FirstOrDefault();
            }

            public override AnyTextGrammar CreateOutput(ParseTree input, ITransformationContext context)
            {
                var grammar = CreateGrammar();
                context.Bag.Empty = grammar.Empty;
                context.Bag.Grammar = grammar;
                context.Bag.String = grammar.String;
                context.Bag.Integer = grammar.Integer;
                context.Bag.Float = grammar.Float;
                context.Bag.Boolean = grammar.Boolean;
                context.Bag.Identifier = grammar.Identifier;
                return grammar;
            }

            protected virtual AnyTextGrammar CreateGrammar()
            {
                var transformation = Transformation as AnyTextTransformation;
                if (transformation != null)
                {
                    return transformation.CreateGrammar();
                }
                else
                {
                    return new AnyTextGrammar();
                }
            }

            public override void RegisterRequirements()
            {
                Call(Rule<LanguageTransformationRule>(), tree => tree.Root);
            }
        }

        class LanguageTransformationRule : SimpleVoidTransformationRule<ParseTreeNode>
        {

            public override void RegisterRequirements()
            {
                RequireMany(Rule<LanguageMemberTransformationRule>(), node => node.ChildNodes[4].ChildNodes);
            }
        }

        class LanguageMemberTransformationRule : AbstractTransformationRule<ParseTreeNode, NonTerminal>
        {
        }

        #region Rule

        class RuleTransformationRule : SimpleTransformationRule<ParseTreeNode, RuleNonTerminal>
        {

            public override RuleNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var ruleNode = GetRuleNode(input);
                var ruleNameNode = ruleNode.ChildNodes[1];
                var ruleNameValue = ruleNameNode.ChildNodes[0].Token.ValueString;
                return new RuleNonTerminal(ruleNameValue);
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<LanguageMemberTransformationRule>(),
                    node => node.ChildNodes.Count == 1
                        && node.ChildNodes[0].Term == AnyText.rule);

                RequireMany(Rule<RuleImplementationTransformationRule>(),
                    node => GetRuleImplementationsNode(node).ChildNodes, PersistExpressions);
            }

            private ParseTreeNode GetRuleImplementationsNode(ParseTreeNode node)
            {
                return GetRuleNode(node).ChildNodes[3];
            }

            private ParseTreeNode GetRuleNode(ParseTreeNode node)
            {
                return node.ChildNodes[0];
            }

            private void PersistExpressions(NonTerminal output, IEnumerable<BnfTermList> expressions)
            {
                output.Rule = new BnfExpression(expressions);
            }
        }

        class RuleImplementationTransformationRule : SimpleTransformationRule<ParseTreeNode, BnfTermList>
        {
            public override void Transform(ParseTreeNode input, BnfTermList output, ITransformationContext context)
            {
                //output of all childs
                var terms = context.Trace.ResolveManyIn(Rule<RulePartTransformationRule>(), input.ChildNodes);

                output.AddRange(terms);
            }

            public override BnfTermList CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                return new BnfTermList();
            }

            public override void RegisterRequirements()
            {
                RequireMany(Rule<RulePartTransformationRule>(), node => node.ChildNodes);
            }
        }

        class RulePartTransformationRule : AbstractTransformationRule<ParseTreeNode, BnfTerm>
        {
        }

        class RuleNameReferenceTransformationRule : SimpleTransformationRule<ParseTreeNode, RuleNonTerminal>
        {
            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(),
                    node => node.ChildNodes[0].Term == AnyText.ruleNameReference);

                OutputDelayLevel = 1;
            }

            public override RuleNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var nameNode = input.ChildNodes[0].ChildNodes[0];
                var name = nameNode.Token.ValueString;
                return context.Trace.FindInWhere
                    (Rule<RuleTransformationRule>(), t => t.Name == name).FirstOrDefault();
            }
        }

        class LiteralTransformationRule : SimpleTransformationRule<ParseTreeNode, BnfTerm>
        {
            public override BnfTerm CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var literal = input.ChildNodes[0];
                var nameNode = GetNameNode(literal);
                var name = nameNode.Token.ValueString;
                AnyTextGrammar grammar = context.Bag.Grammar;
                return grammar.ToTerm(name);
            }

            protected virtual ParseTreeNode GetNameNode(ParseTreeNode literalNode)
            {
                return literalNode.ChildNodes[0];
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(),
                    node => node.ChildNodes[0].Term == AnyText.String);
            }
        }

        class KeywordTransformationRule : LiteralTransformationRule
        {

            protected override ParseTreeNode GetNameNode(ParseTreeNode identifierNode)
            {
                return identifierNode.ChildNodes[2];
            }

            public override void Transform(ParseTreeNode input, BnfTerm output, ITransformationContext context)
            {
                AnyTextGrammar grammar = context.Bag.Grammar;
                grammar.MarkReservedWords(output.Name);
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(),
                    node => node.ChildNodes[0].Term == AnyText.keyword);
            }
        }

        class IdentifierTransformationRule : SimpleTransformationRule<ParseTreeNode, Identifier>
        {
            public override Identifier CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var identifierNode = input.ChildNodes[0];
                var nameNode = identifierNode.ChildNodes[2];
                var name = nameNode.Token.ValueString;
                var ident = new Identifier(name, context.Bag.Identifier);
                ident.IsUnique = true;
                return ident;
            }

            public override void Transform(ParseTreeNode input, Identifier output, ITransformationContext context)
            {
                AnyTextGrammar grammar = context.Bag.Grammar;
                grammar.Identifiers.Add(output);
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<TypeExpressionRule>(),
                    node => node.ChildNodes[0].Term == AnyText.identifier);
            }
        }

        class IdentifierReferenceTransformationRule : SimpleTransformationRule<ParseTreeNode, IdentifierReference>
        {
            public override IdentifierReference CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var identifierNode = input.ChildNodes[0];
                var nameNode = identifierNode.ChildNodes[2];
                var name = nameNode.Token.ValueString;
                var reference = new IdentifierReference(name, context.Bag.Identifier);
                return reference;
            }

            public override void Transform(ParseTreeNode input,  IdentifierReference output, ITransformationContext context)
            {
                AnyTextGrammar grammar = context.Bag.Grammar;

                var ident = context.Trace.FindInWhere(Rule<IdentifierTransformationRule>(),
                                id => id.Name == output.Name).FirstOrDefault();

                if (ident != null)
                {
                    output.Identifier = ident;
                    output.MustExist = true;
                }
                else
                {
                    output.MustExist = false;
                }

                grammar.References.Add(output);
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<TypeExpressionRule>(),
                    node => node.ChildNodes[0].Term == AnyText.reference);
            }
        }

        abstract class OperatorTransformationRule : SimpleTransformationRule<ParseTreeNode, NonTerminal>
        {
            public override NonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                return new NonTerminal(null);
            }

            public override void Transform(ParseTreeNode input, NonTerminal output, ITransformationContext context)
            {
                AnyTextGrammar grammar = context.Bag.Grammar;
                RegisterOperator(output, context.Trace.ResolveIn(Rule<RulePartTransformationRule>(), 
                    GetChildNode(input)), grammar);
            }

            public ParseTreeNode GetChildNode(ParseTreeNode input)
            {
                return input.ChildNodes[0].ChildNodes[0];
            }

            protected internal abstract void RegisterOperator(NonTerminal output, BnfTerm bnfExpression, AnyTextGrammar grammar);

            protected internal abstract BnfTerm NeccessaryTerm { get; }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(),
                    node => node.ChildNodes[0].Term == NeccessaryTerm);

                Require(Rule<RulePartTransformationRule>(),
                    node => GetChildNode(node));
            }
        }

        class QuestionMarkTransformationRule : OperatorTransformationRule
        {

            protected internal override BnfTerm NeccessaryTerm
            {
                get { return AnyText.qmark; }
            }

            protected internal override void RegisterOperator(NonTerminal output, BnfTerm bnfExpression, AnyTextGrammar grammar)
            {
                output.Rule = bnfExpression | grammar.Empty;
                output.Name = bnfExpression.Name + "?";
            }
        }

        class PlusTransformationRule : OperatorTransformationRule
        {
            protected internal override BnfTerm NeccessaryTerm
            {
                get { return AnyText.plus; }
            }

            protected internal override void RegisterOperator(NonTerminal output, BnfTerm bnfExpression, AnyTextGrammar grammar)
            {
                output.Rule = grammar.MakePlusRule(output, null, bnfExpression);
                output.Name = bnfExpression.Name + "+";
            }
        }

        class StarTransformationRule : OperatorTransformationRule
        {
            protected internal override void RegisterOperator(NonTerminal output, BnfTerm bnfExpression, AnyTextGrammar grammar)
            {
                output.Rule = grammar.MakeStarRule(output, null, bnfExpression);
                output.Name = bnfExpression.Name + "*";
            }

            protected internal override BnfTerm NeccessaryTerm
            {
                get { return AnyText.star; }
            }
        }

        class ParanthesisRule : SimpleTransformationRule<ParseTreeNode, NonTerminal>
        {
            public override NonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                return new NonTerminal(input.ChildNodes[0].ToString());
            }

            public override void Transform(ParseTreeNode input, NonTerminal output, ITransformationContext context)
            {
                AnyTextGrammar grammar = context.Bag.Grammar;

                Register(output, context.Trace.ResolveManyIn(Rule<RuleImplementationTransformationRule>(), 
                    GetChildNodes(input)), grammar);
            }

            public IEnumerable<ParseTreeNode> GetChildNodes(ParseTreeNode input)
            {
                return input.ChildNodes[0].ChildNodes[1].ChildNodes;
            }

            protected internal void Register(NonTerminal output, IEnumerable<BnfTermList> bnfExpressions, AnyTextGrammar grammar)
            {
                output.Rule = new BnfExpression(bnfExpressions);
                output.Name = "(" + string.Join("|", bnfExpressions.Select(list => string.Join(string.Empty, list.Select(term => term.Name)))) + ")";
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(),
                    node => node.ChildNodes[0].Term == AnyText.paranthesis);

                RequireMany(Rule<RuleImplementationTransformationRule>(),
                    GetChildNodes);
            }
        }

        abstract class RulePartChildAdornerTransformationRule : SimpleTransformationRule<ParseTreeNode, BnfTerm>
        {
            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(),
                    node => node.ChildNodes[0].Term == NeccessaryExpression);

                Require(Rule<RulePartTransformationRule>(),
                    node => GetChildNode(node));
            }

            protected abstract BnfTerm NeccessaryExpression { get; }

            protected virtual ParseTreeNode GetChildNode(ParseTreeNode node)
            {
                return node.ChildNodes[0].ChildNodes[0];
            }

            public override BnfTerm CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                return context.Trace.ResolveIn(Rule<RulePartTransformationRule>(),
                    (GetChildNode(input)));
            }
        }

        class PropertyTransformationRule : SimpleTransformationRule<ParseTreeNode, TypedNonTerminal>
        {
            protected ParseTreeNode GetChildNode(ParseTreeNode node)
            {
                return node.ChildNodes[0].ChildNodes[2];
            }

            protected ParseTreeNode GetNameNode(ParseTreeNode node)
            {
                return node.ChildNodes[0].ChildNodes[0];
            }

            public override void Transform(ParseTreeNode input, TypedNonTerminal output, ITransformationContext context)
            {
                var prop = new PropertyInfo(output);
                var nameNode = GetNameNode(input);
                prop.Name = nameNode.Token.ValueString;
                output.Property = prop;
                prop.IsCollection = input.ChildNodes[0].ChildNodes[1].Term == AnyText.increment;
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(),
                    node => node.ChildNodes[0].Term == AnyText.property);

                Require(Rule<TypeExpressionRule>(),
                    node => GetChildNode(node));
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                return context.Trace.ResolveIn(Rule<TypeExpressionRule>(),
                            GetChildNode(input));
            }

        }

        class InheritanceTransformationRule : SimpleTransformationRule<ParseTreeNode, RuleNonTerminal>
        {
            protected ParseTreeNode GetChildNode(ParseTreeNode node)
            {
                return node.ChildNodes[0].ChildNodes[2].ChildNodes[0];
            }

            public override void Transform(ParseTreeNode input, RuleNonTerminal output, ITransformationContext context)
            {
                output.IsInheritance = true;
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(), 
                    node => node.ChildNodes[0].Term == AnyText.inherited);

                OutputDelayLevel = 1;
            }

            public override RuleNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var ruleName = (string)GetChildNode(input).Token.Value;
                return context.Trace.FindInWhere(Rule<RuleTransformationRule>(), r => r.Name == ruleName).FirstOrDefault();
            }

        }

        #endregion

        #region Type

        class TypeExpressionRule : AbstractTransformationRule<ParseTreeNode, TypedNonTerminal>
        {
        }

        class TypeTransformationRule : SimpleTransformationRule<ParseTreeNode, TypedNonTerminal>
        {
            protected ParseTreeNode GetChildNode(ParseTreeNode node)
            {
                return node.ChildNodes[0].ChildNodes[3];
            }

            protected ParseTreeNode GetNameNode(ParseTreeNode node)
            {
                return node.ChildNodes[0].ChildNodes[1];
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var type = context.Trace.ResolveIn(Rule<TypeExpressionRule>(),
                    GetChildNode(input));

                var nameNode = GetNameNode(input);

                type.Name = nameNode.ChildNodes[0].Token.ValueString;

                return type;
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<LanguageMemberTransformationRule>(), node => node.ChildNodes[0].Term == AnyText.type);

                Require(Rule<TypeExpressionRule>(), new Func<ParseTreeNode, ParseTreeNode>(GetChildNode));
            }
        }

        class TypeReferenceTransformationRule : DataTypeTransformationRule
        {
            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var nameNode = GetDataTypeNode(input).ChildNodes[2];
                var name = nameNode.ChildNodes[0].Token.ValueString;
                return context.Trace.FindInWhere(Rule<TypeTransformationRule>(), type => type.Name == name).FirstOrDefault();
            }

            public override void RegisterRequirements()
            {
                OutputDelayLevel = 1;

                MarkInstantiatingFor(Rule<TypeExpressionRule>(), node => node.ChildNodes[0].Term == AnyText.typeRef);
            }

            protected override BnfTerm NeccessaryExpression
            {
                get { return AnyText.typeRef; }
            }
        }

        class RuleReferenceTransformationRule : SimpleTransformationRule<ParseTreeNode, TypedNonTerminal>
        {
            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var nameNode = input.ChildNodes[0].ChildNodes[2];
                var name = nameNode.ChildNodes[0].Token.ValueString;
                return context.Trace.FindInWhere(Rule<RuleTransformationRule>(),
                    rule => rule.Name == name).FirstOrDefault();
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<TypeExpressionRule>(),
                     node => node.ChildNodes[0].Term == AnyText.ruleReference);

                OutputDelayLevel = 1;
            }
        }

        class TypeExpressionTransformationRule : SimpleTransformationRule<ParseTreeNode, TypedNonTerminal>
        {
            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<RulePartTransformationRule>(),
                    node => node.ChildNodes[0].Term == AnyText.typeExpression);

                Require(Rule<TypeExpressionRule>(),
                    node => GetChildNode(node));
            }

            protected virtual ParseTreeNode GetChildNode(ParseTreeNode node)
            {
                return node.ChildNodes[0].ChildNodes[0];
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                return context.Trace.ResolveIn(Rule<TypeExpressionRule>(), 
                    GetChildNode(input));
            }
        }

        abstract class DataTypeTransformationRule : SimpleTransformationRule<ParseTreeNode, TypedNonTerminal>
        {
            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<TypeExpressionRule>(), 
                    node => node.ChildNodes[0].Term == NeccessaryExpression);
            }

            protected ParseTreeNode GetDataTypeNode(ParseTreeNode node)
            {
                return node.ChildNodes[0];
            }

            protected ParseTreeNode GetOptionsNode(ParseTreeNode baseNode)
            {
                return baseNode.ChildNodes[0].ChildNodes[1];
            }

            protected abstract BnfTerm NeccessaryExpression { get; }
        }

        abstract class CustomizableDataTypeTransformationRule : DataTypeTransformationRule
        {
            public override void RegisterRequirements()
            {
                base.RegisterRequirements();

                CallManyOutputSensitive(Rule<BaseOptionTransformationRule>(),
                    (node, typeTerminal) => GetOptions(node).PairWithConstant(typeTerminal.Type));
            }

            protected IEnumerable<ParseTreeNode> GetOptions(ParseTreeNode node)
            {
                var optionsOpt = GetOptionsNode(node);
                if (optionsOpt == null) return null;
                return optionsOpt.ChildNodes[1].ChildNodes;
            }
        }

        class BaseOptionTransformationRule : SimpleVoidTransformationRule<ParseTreeNode, TypeReference> { }

        abstract class CustomizableOptionTransformationRule<T> : SimpleVoidTransformationRule<ParseTreeNode, T>
            where T : DataType
        {
            public override void RegisterRequirements()
            {
                CallFor((node, dt) => node.ChildNodes[0].Term == NecessaryExpression && dt is T);
            }

            protected abstract BnfTerm NecessaryExpression
            {
                get;
            }

            public object GetValue(ParseTreeNode baseNode)
            {
                var valueNode = baseNode.ChildNodes[0].ChildNodes[2];
                var type = valueNode.Term as DataTypeTerminal;
                if (type != null)
                {
                    return type.GetValue(valueNode);
                }
                else
                {
                    return null;
                }
            }
        }

        class StringTransformationRule : CustomizableDataTypeTransformationRule
        {
            protected override BnfTerm NeccessaryExpression
            {
                get { return AnyText.@string; }
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var options = GetOptionsNode(input);
                var stringType = context.Bag.String as DataTypeTerminal<StringType>;
                if (options.ChildNodes.Count == 0)
                {
                    return stringType;
                }
                else
                {
                    return stringType.CreateCustom();
                }
            }
        }

        class StringLengthTransformationRule : CustomizableOptionTransformationRule<StringType>
        {
            public override void Transform(ParseTreeNode input, StringType type, ITransformationContext context)
            {
                var o = GetValue(input);
                if (o != null) type.MaxLength = Convert.ToInt32(o);
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.stringMaxLength; }
            }
        }

        class IntegerTransformationRule : CustomizableDataTypeTransformationRule
        {
            protected override BnfTerm NeccessaryExpression
            {
                get { return AnyText.integer; }
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var options = GetOptionsNode(input);
                var integer = context.Bag.Integer as DataTypeTerminal<IntegerType>;
                if (options.ChildNodes.Count == 0)
                {
                    return integer;
                }
                else
                {
                    return integer.CreateCustom();
                }
            }
        }

        class IntegerMaximumRule : CustomizableOptionTransformationRule<IntegerType>
        {
            public override void Transform(ParseTreeNode input, IntegerType type, ITransformationContext context)
            {
                var o = GetValue(input);
                if (o != null) type.Maximum = (long)o;
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.intMaximum; }
            }
        }

        class IntegerMinimumRule : CustomizableOptionTransformationRule<IntegerType>
        {
            public override void Transform(ParseTreeNode input, IntegerType type, ITransformationContext context)
            {
                var o = GetValue(input);
                if (o != null) type.Minimum = Convert.ToInt64(o);
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.intMinimum; }
            }
        }

        class FloatTransformationRule : CustomizableDataTypeTransformationRule
        {
            protected override BnfTerm NeccessaryExpression
            {
                get { return AnyText.@float; }
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var options = GetOptionsNode(input);
                var floatType = context.Bag.Float as DataTypeTerminal<FloatType>;
                if (options.ChildNodes.Count == 0)
                {
                    return floatType;
                }
                else
                {
                    return floatType.CreateCustom();
                }
            }
        }

        class FloatMaximumRule : CustomizableOptionTransformationRule<FloatType>
        {
            public override void Transform(ParseTreeNode input, FloatType type, ITransformationContext context)
            {
                var o = GetValue(input);
                if (o != null) type.Maximum = Convert.ToDouble(o);
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.floatMaximum; }
            }
        }

        class FloatMinimumRule : CustomizableOptionTransformationRule<FloatType>
        {
            public override void Transform(ParseTreeNode input, FloatType type, ITransformationContext context)
            {
                var o = GetValue(input);
                if (o != null) type.Minimum = Convert.ToDouble(o);
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.floatMinimum; }
            }
        }


        class BooleanTransformationRule : CustomizableDataTypeTransformationRule
        {
            protected override BnfTerm NeccessaryExpression
            {
                get { return AnyText.boolean; }
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var options = GetOptionsNode(input);
                var boolean = context.Bag.Boolean as DataTypeTerminal<BooleanType>;
                if (options.ChildNodes.Count == 0)
                {
                    return boolean;
                }
                else
                {
                    return boolean.CreateCustom();
                }
            }
        }

        class BooleanFalseStringRule : CustomizableOptionTransformationRule<BooleanType>
        {
            public override void Transform(ParseTreeNode input, BooleanType type, ITransformationContext context)
            {
                type.FalseString = (string)GetValue(input);
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.booleanFalseString; }
            }
        }

        class BooleanTrueStringRule : CustomizableOptionTransformationRule<BooleanType>
        {
            public override void Transform(ParseTreeNode input, BooleanType type, ITransformationContext context)
            {
                type.TrueString = (string)GetValue(input);
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.booleanTrueString; }
            }
        }

        class RegexTransformationRule : StringTransformationRule
        {
            protected override BnfTerm NeccessaryExpression
            {
                get { return AnyText.regex; }
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                AnyTextGrammar grammar = context.Bag.Grammar as AnyTextGrammar;
                return grammar.CreateRegex();
            }
        }

        class RegexPatternRule : CustomizableOptionTransformationRule<RegexType>
        {
            public override void Transform(ParseTreeNode input, RegexType type, ITransformationContext context)
            {
                type.Regex = new System.Text.RegularExpressions.Regex((string)GetValue(input));
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.regexPattern; }
            }
        }

        class RegexMultilineRule : CustomizableOptionTransformationRule<RegexType>
        {
            public override void Transform(ParseTreeNode input, RegexType type, ITransformationContext context)
            {
                throw new NotSupportedException();
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.regexMultiline; }
            }
        }



        class EnumTransformationRule : CustomizableDataTypeTransformationRule
        {
            protected override BnfTerm NeccessaryExpression
            {
                get { return AnyText.@enum; }
            }

            public override TypedNonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                var grammar = context.Bag.Grammar as AnyTextGrammar;
                return grammar.CreateEnum();
            }
        }

        class EnumIgnoreCaseRule : CustomizableOptionTransformationRule<EnumType>
        {
            public override void Transform(ParseTreeNode input, EnumType type, ITransformationContext context)
            {
                type.IgnoreCase = false;
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.enumIgnoreCase; }
            }
        }

        class EnumLiteral : CustomizableOptionTransformationRule<EnumType>
        {
            public override void Transform(ParseTreeNode input, EnumType type, ITransformationContext context)
            {
                type.Literals.Add((string)GetValue(input));
            }

            protected override BnfTerm NecessaryExpression
            {
                get { return AnyText.String; }
            }
        }



        #endregion

        #region IdentifierDefaults

        class IdentifierDefaultsSectionTransformationRule : SimpleTransformationRule<ParseTreeNode, NonTerminal>
        {
            public override void Transform(ParseTreeNode input, NonTerminal output, ITransformationContext context)
            {
                var nameNode = input.ChildNodes[0].ChildNodes[1];
                var name = nameNode.Token.ValueString;
                var identifier = context.Trace.FindInWhere(Rule<IdentifierTransformationRule>(),
                    ident => ident.Name == name).FirstOrDefault();

                if (identifier == null)
                    //TODO: better way of recognizing an error here, something like ParserError
                    throw new ArgumentOutOfRangeException();

                var list = context.Trace.ResolveIn(Rule<IdentifierDefaultsTransformationRule>(),
                    input.ChildNodes[0].ChildNodes[3]);

                identifier.DefaultValues.AddRange(list);
            }

            public override NonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                return null;
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<LanguageMemberTransformationRule>(),
                    node => node.ChildNodes[0].Term == AnyText.identifierDefaultsSection);

                Require(Rule<IdentifierDefaultsTransformationRule>(),
                    node => node.ChildNodes[0].ChildNodes[3]);
            }
        }

        class IdentifierDefaultsTransformationRule : SimpleTransformationRule<ParseTreeNode, List<string>>
        {
            public override void Transform(ParseTreeNode input, List<string> output, ITransformationContext context)
            {
                foreach (var item in input.ChildNodes)
                {
                    var val = item.ChildNodes[0].Token.Value;
                    output.Add(val == null ? "" : val.ToString());
                }
            }
        }

        #endregion

        #region Comments

        class CommentsTransformationRule : SimpleTransformationRule<ParseTreeNode, NonTerminal>
        {
            public override void Transform(ParseTreeNode input, NonTerminal output, ITransformationContext context)
            {
                var switchNode = input.ChildNodes[0].ChildNodes[0];
                var grammar = context.Bag.Grammar as AnyTextGrammar;

                if (switchNode.Term == AnyText.singleLineComment)
                {
                    var argument = GetString(switchNode.ChildNodes[2]);
                    grammar.AddSingleLineComment(argument);
                }
                else
                {
                    var argument1 = GetString(switchNode.ChildNodes[2]);
                    var argument2 = GetString(switchNode.ChildNodes[4]);

                    grammar.AddMultiLineComment(argument1, argument2);
                }
            }

            public override NonTerminal CreateOutput(ParseTreeNode input, ITransformationContext context)
            {
                return null;
            }

            private string GetString(ParseTreeNode parseTreeNode)
            {
                var s = parseTreeNode.ChildNodes[0].Token.Value;
                return s == null ? "" : s.ToString();
            }

            public override void RegisterRequirements()
            {
                MarkInstantiatingFor(Rule<LanguageMemberTransformationRule>(),
                    node => node.ChildNodes[0].Term == AnyText.comments);
            }
        }

        #endregion
    }
}
